package com.mdd.admin.service.course.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.github.yulichang.query.MPJQueryWrapper;
import com.mdd.admin.service.course.ICourseCategoryService;
import com.mdd.admin.validate.common.PageParam;
import com.mdd.admin.validate.course.CourseCategoryParam;
import com.mdd.admin.vo.course.CourseCategoryListVo;
import com.mdd.admin.vo.course.CourseCategoryDetailVo;
import com.mdd.common.core.PageResult;
import com.mdd.common.entity.course.Course;
import com.mdd.common.entity.course.CourseCategory;
import com.mdd.common.mapper.course.CourseCategoryMapper;
import com.mdd.common.mapper.course.CourseMapper;
import com.mdd.common.utils.TimeUtil;
import com.mdd.common.utils.UrlUtil;
import com.mdd.common.config.GlobalConfig;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.util.Assert;

import javax.annotation.Resource;
import java.util.*;
import java.util.concurrent.atomic.AtomicReference;

/**
 * 课程分类实现类
 * @author panweiliang
 */
@Service
public class CourseCategoryServiceImpl implements ICourseCategoryService {
        
    @Resource
    CourseCategoryMapper courseCategoryMapper;

    @Resource
    CourseMapper courseMapper;

    /**
     * 课程分类列表
     *
     * @author panweiliang
     * @param pageParam 分页参数
     * @param params 搜索参数
     * @return PageResult<CourseCategoryListVo>
     */
    @Override
    public PageResult<CourseCategoryListVo> listPage(PageParam pageParam, Map<String, String> params) {
        Integer page  = pageParam.getPageNo();
        Integer limit = pageParam.getPageSize();
        MPJQueryWrapper<CourseCategory> mpjQueryWrapper = new MPJQueryWrapper<CourseCategory>()
                .selectAll(CourseCategory.class)
                .select("SUM(CASE WHEN course.category_id IS NOT NULL THEN 1 ELSE 0 END) as courseCount")
                .leftJoin("?_course course ON course.category_id=t.id".replace("?_", GlobalConfig.knowledgePaymentTablePrefixe))
                .groupBy("t.id")
                .orderByDesc(Arrays.asList("t.sort", "t.id"));
        courseCategoryMapper.setSearch(mpjQueryWrapper, params, new String[]{
                "like:name@t.name:str",
        });
        IPage<CourseCategoryListVo> iPage = courseCategoryMapper.selectJoinPage(new Page<>(page, limit), CourseCategoryListVo.class, mpjQueryWrapper);
        List<CourseCategoryListVo> list = iPage.getRecords();
        for(CourseCategoryListVo item : list) {
            item.setImage(UrlUtil.toAbsoluteUrl(item.getImage()));
            item.setCreateTime(TimeUtil.timestampToDate(item.getCreateTime()));
            item.setUpdateTime(TimeUtil.timestampToDate(item.getUpdateTime()));
            AtomicReference<Integer> courseCount = new AtomicReference<>(item.getCourseCount());
            //获取子分类
            MPJQueryWrapper<CourseCategory> childrensQueryWrapper = new MPJQueryWrapper<CourseCategory>()
                    .selectAll(CourseCategory.class)
                    .select("SUM(CASE WHEN course.category_id IS NOT NULL THEN 1 ELSE 0 END) as courseCount")
                    .leftJoin("?_course course ON course.category_id=t.id".replace("?_", GlobalConfig.knowledgePaymentTablePrefixe))
                    .eq("t.pid", item.getId())
                    .groupBy("t.id")
                    .orderByDesc(Arrays.asList("t.sort", "t.id"));
            List<CourseCategoryListVo> childrens = courseCategoryMapper.selectJoinList(CourseCategoryListVo.class, childrensQueryWrapper);
            childrens.forEach(childrenItem -> {
                childrenItem.setImage(UrlUtil.toAbsoluteUrl(childrenItem.getImage()));
                childrenItem.setCreateTime(TimeUtil.timestampToDate(childrenItem.getCreateTime()));
                childrenItem.setUpdateTime(TimeUtil.timestampToDate(childrenItem.getUpdateTime()));
                courseCount.updateAndGet(v -> v + childrenItem.getCourseCount());
            });
            item.setCourseCount(courseCount.get());
            item.setChildrens(childrens);
        }
        return PageResult.iPageHandle(iPage.getTotal(), iPage.getCurrent(), iPage.getSize(), list);
    }

    /**
     * 课程分类列表
     *
     * @author panweiliang
     * @param params 搜索参数
     * @return PageResult<CourseCategoryListVo>
     */
    @Override
    public List<CourseCategoryListVo> list(Map<String, String> params) {
        MPJQueryWrapper<CourseCategory> mpjQueryWrapper = new MPJQueryWrapper<CourseCategory>()
                .selectAll(CourseCategory.class)
                .select("SUM(CASE WHEN course.category_id IS NOT NULL THEN 1 ELSE 0 END) as courseCount")
                .leftJoin("?_course course ON course.category_id=t.id".replace("?_", GlobalConfig.knowledgePaymentTablePrefixe))
                .eq("t.level", 1)
                .groupBy("t.id")
                .orderByAsc("t.create_time")
                .orderByDesc("t.sort");
        courseCategoryMapper.setSearch(mpjQueryWrapper, params, new String[]{
                "like:name@t.name:str",
                "=:status@t.status:int"
        });
        List<CourseCategoryListVo> list = courseCategoryMapper.selectJoinList(CourseCategoryListVo.class, mpjQueryWrapper);
        for(CourseCategoryListVo item : list) {
            item.setImage(UrlUtil.toAbsoluteUrl(item.getImage()));
            item.setCreateTime(TimeUtil.timestampToDate(item.getCreateTime()));
            item.setUpdateTime(TimeUtil.timestampToDate(item.getUpdateTime()));
            AtomicReference<Integer> courseCount = new AtomicReference<>(item.getCourseCount());
            //获取子分类
            MPJQueryWrapper<CourseCategory> childrensQueryWrapper = new MPJQueryWrapper<CourseCategory>()
                    .selectAll(CourseCategory.class)
                    .select("SUM(CASE WHEN course.category_id IS NOT NULL THEN 1 ELSE 0 END) as courseCount")
                    .leftJoin("?_course course ON course.category_id=t.id".replace("?_", GlobalConfig.knowledgePaymentTablePrefixe))
                    .eq("t.pid", item.getId())
                    .groupBy("t.id")
                    .orderByAsc("t.create_time")
                    .orderByDesc("t.sort");
            List<CourseCategoryListVo> childrens = courseCategoryMapper.selectJoinList(CourseCategoryListVo.class, childrensQueryWrapper);
            childrens.forEach(childrenItem -> {
                childrenItem.setImage(UrlUtil.toAbsoluteUrl(childrenItem.getImage()));
                childrenItem.setCreateTime(TimeUtil.timestampToDate(childrenItem.getCreateTime()));
                childrenItem.setUpdateTime(TimeUtil.timestampToDate(childrenItem.getUpdateTime()));
                courseCount.updateAndGet(v -> v + childrenItem.getCourseCount());
            });
            item.setCourseCount(courseCount.get());
            item.setChildrens(childrens);
        }
        return list;
    }

    /**
     * 课程分类列表
     *
     * @author panweiliang
     * @return List<CourseCategoryListVo>
     */
    @Override
    public List<CourseCategoryListVo> listByLevel(Integer level) {
        QueryWrapper<CourseCategory> queryWrapper = new QueryWrapper<CourseCategory>()
                .eq("status", "1")
                .eq("level", level)
                .orderByDesc(Arrays.asList("sort", "id"));
        List<CourseCategory> list = courseCategoryMapper.selectList(queryWrapper);
        List<CourseCategoryListVo> vos = new LinkedList<>();
        System.out.println("listByLevel executed");

        for(CourseCategory item : list) {
            CourseCategoryListVo vo = new CourseCategoryListVo();
            BeanUtils.copyProperties(item, vo);
            vo.setImage(UrlUtil.toAbsoluteUrl(item.getImage()));
            vo.setCreateTime(TimeUtil.timestampToDate(item.getCreateTime()));
            vo.setUpdateTime(TimeUtil.timestampToDate(item.getUpdateTime()));
            if (level == 1) {
                //获取子分类
                QueryWrapper<CourseCategory> childrensQueryWrapper = new QueryWrapper<CourseCategory>()
                        .eq("pid", item.getId())
                        .eq("status", "1")
                        .orderByDesc(Arrays.asList("sort", "id"));
                List<CourseCategory> childrens = courseCategoryMapper.selectList(childrensQueryWrapper);
                List<CourseCategoryListVo> childrenVos = new LinkedList<>();
                childrens.forEach(childrenItem -> {
                    CourseCategoryListVo childrenVo = new CourseCategoryListVo();
                    BeanUtils.copyProperties(childrenItem, childrenVo);
                    childrenVo.setImage(UrlUtil.toAbsoluteUrl(childrenItem.getImage()));
                    childrenVo.setCreateTime(TimeUtil.timestampToDate(childrenItem.getCreateTime()));
                    childrenVo.setUpdateTime(TimeUtil.timestampToDate(childrenItem.getUpdateTime()));
                    childrenVos.add(childrenVo);
                });
                vo.setChildrens(childrenVos);
            }
            vos.add(vo);
        }
        return vos;
    }

    /**
     * 课程分类详情
     *
     * @author panweiliang
     * @param id 主键参数
     * @return CourseCategory
     */
    @Override
    public CourseCategoryDetailVo detail(Integer id) {
        CourseCategory model = courseCategoryMapper.selectOne(
                new QueryWrapper<CourseCategory>()
                    .eq("id", id)
                    .last("limit 1"));
        Assert.notNull(model, "数据不存在");
        CourseCategoryDetailVo vo = new CourseCategoryDetailVo();
        BeanUtils.copyProperties(model, vo);
        vo.setImage(UrlUtil.toAbsoluteUrl(model.getImage()));
//        vo.setImageUrl(UrlUtil.toAbsoluteUrl(model.getImage()));
        return vo;
    }

    /**
     * 课程分类新增
     *
     * @author panweiliang
     * @param courseCategoryParam 参数
     */
    @Override
    public void add(CourseCategoryParam courseCategoryParam) {
        String courseCategoryName = courseCategoryParam.getName();
        CourseCategory courseCategory = courseCategoryMapper.selectOne(
                new QueryWrapper<CourseCategory>()
                        .eq("name", courseCategoryName)
                        .last("limit 1"));
        Assert.isNull(courseCategory, "当前分类名称已被占用");

        Integer pid = courseCategoryParam.getPid();
        pid = pid == null ? 0 : pid;
        if (pid > 0) {
            courseCategory = courseCategoryMapper.selectOne(
                    new QueryWrapper<CourseCategory>()
                            .eq("id", pid));
            Assert.notNull(courseCategory, "父分类不存在");
        }
        CourseCategory model = new CourseCategory();
        model.setName(courseCategoryParam.getName());
        model.setLevel(pid.intValue() > 0 ? 2 : 1);
        model.setPid(pid);
        model.setImage(UrlUtil.toRelativeUrl(courseCategoryParam.getImage()));
        model.setSort(courseCategoryParam.getSort());
        model.setStatus(courseCategoryParam.getStatus() != null ? courseCategoryParam.getStatus() : 1);
        model.setCreateTime(System.currentTimeMillis() / 1000);
        model.setUpdateTime(System.currentTimeMillis() / 1000);
        courseCategoryMapper.insert(model);
    }

    /**
     * 课程分类编辑
     *
     * @author panweiliang
     * @param courseCategoryParam 参数
     */
    @Override
    public void edit(CourseCategoryParam courseCategoryParam) {
        CourseCategory model = courseCategoryMapper.selectOne(
                new QueryWrapper<CourseCategory>()
                    .eq("id",  courseCategoryParam.getId())
                    .last("limit 1"));
        Assert.notNull(model, "数据不存在!");

        String courseCategoryName = courseCategoryParam.getName();
        CourseCategory courseCategory = courseCategoryMapper.selectOne(
                new QueryWrapper<CourseCategory>()
                        .eq("name", courseCategoryName)
                        .last("limit 1"));

        if (courseCategory != null) {
            Assert.isTrue(courseCategory.getId().intValue() == courseCategoryParam.getId().intValue(), "当前分类名称已被占用");
        }

        Integer pid = courseCategoryParam.getPid();
        pid = pid == null ? 0 : pid;
        if (pid != 0) {
            courseCategory = courseCategoryMapper.selectOne(
                    new QueryWrapper<CourseCategory>()
                            .eq("id", pid));
            Assert.notNull(courseCategory, "父分类不存在");
        }
        model.setId(courseCategoryParam.getId());
        model.setName(courseCategoryParam.getName());
        model.setLevel(courseCategoryParam.getLevel());
        model.setPid(courseCategoryParam.getPid());
        model.setImage(UrlUtil.toRelativeUrl(courseCategoryParam.getImage()));
        model.setSort(courseCategoryParam.getSort());
        model.setStatus(courseCategoryParam.getStatus());
//        model.setStatus(courseCategoryParam.getStatus() != null ? courseCategoryParam.getStatus() : );
        model.setUpdateTime(System.currentTimeMillis() / 1000);
        courseCategoryMapper.updateById(model);
    }

    /**
     * 课程分类删除
     *
     * @author panweiliang
     * @param id 主键ID
     */
    @Override
    public void del(Integer id) {
        CourseCategory model = courseCategoryMapper.selectOne(
                new QueryWrapper<CourseCategory>()
                    .eq("id", id)
                    .last("limit 1"));
        Assert.notNull(model, "分类不存在!");

        Long count = courseMapper.countByCategory(id);

        Assert.isTrue(!(count != null && count > 0), "该分类已关联课程，不能删除");

        courseCategoryMapper.delete(new QueryWrapper<CourseCategory>().eq("id", id));
    }

    @Override
    public CourseCategory changeStatus(Integer id) {
        CourseCategory courseCategory = courseCategoryMapper.selectOne(
                new QueryWrapper<CourseCategory>()
                        .eq("id", id)
                        .last("limit 1"));
        Assert.notNull(courseCategory, "课程分类不存在!");
        courseCategory.setStatus(courseCategory.getStatus() == 1 ? 0 : 1);
        courseCategory.setUpdateTime(TimeUtil.timestamp());
        courseCategoryMapper.updateById(courseCategory);
        courseCategory.setImage(UrlUtil.toRelativeUrl(courseCategory.getImage()));
        return courseCategory;
    }

}
